//
//  WiteBoxAsserts.h
//  WiteBox
//
//  Created by John Blanco on 1/21/10.
//  Copyright 2010 Effective UI. All rights reserved.
//

#import <Foundation/Foundation.h>

// default decimal delta (since you can't test directly)
static double const DEFAULT_DELTA = 0.00001;

// equality assertions
#define ASSERT_INTEGERS_EQUAL(E, A) if ((E) != (A)) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertIntegersEqual" expectedValue:[NSString stringWithFormat:@"%i", (E)] actualValue:[NSString stringWithFormat:@"%i", (A)] filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_DECIMALS_EQUAL(E, A) ASSERT_DECIMALS_EQUAL_WITH_DELTA(E, A, DEFAULT_DELTA)
#define ASSERT_DECIMALS_EQUAL_WITH_DELTA(E, A, D) if (ABS((E) - (A)) > (D)) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertDecimalsEqual" expectedValue:[NSString stringWithFormat:@"%g", (E)] actualValue:[NSString stringWithFormat:@"%g", (A)] filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_STRINGS_EQUAL(E, A) if (![(E) isEqualToString:(A)]) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertStringsEqual" expectedValue:(E) actualValue:(A) filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_STRINGS_INSENSITIVE_EQUAL(E, A) if ([(E) caseInsensitiveCompare:(A)] != NSOrderedSame) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertStringsInsensitiveEqual" expectedValue:[NSString stringWithFormat:@"/%@/i", (E)] actualValue:(A) filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_OBJECTS_EQUAL(E, A) if (![(E) isEqual:(A)]) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertObjectsEqual" expectedValue:@"equal objects" actualValue:@"unequal objects" filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_OBJECTS_IDENTICAL(E, A) if ((E) != (A)) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertObjectsIdentical" expectedValue:@"identical objects" actualValue:@"unidentical objects" filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_NIL(A) if (A) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertNil" expectedValue:@"null" actualValue:@"!null" filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }

// inequality assertions
#define ASSERT_INTEGERS_NOT_EQUAL(E, A) if ((E) == (A)) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertIntegersNotEqual" expectedValue:[NSString stringWithFormat:@"!%i", (E)] actualValue:[NSString stringWithFormat:@"%i", (A)] filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_DECIMALS_NOT_EQUAL(E, A) ASSERT_DECIMALS_NOT_EQUAL_WITH_DELTA(E, A, DEFAULT_DELTA)
#define ASSERT_DECIMALS_NOT_EQUAL_WITH_DELTA(E, A, D) if (ABS((E) - (A)) <= (D)) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertDecimalsNotEqual" expectedValue:[NSString stringWithFormat:@"!%g", (E)] actualValue:[NSString stringWithFormat:@"%g", (A)] filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_STRINGS_NOT_EQUAL(E, A) if ([(E) isEqualToString:(A)]) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertStringsNotEqual" expectedValue:[NSString stringWithFormat:@"!%@", (E)] actualValue:(A) filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_STRINGS_INSENSITIVE_NOT_EQUAL(E, A) if ([(E) caseInsensitiveCompare:(A)] == NSOrderedSame) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertStringsInsensitiveNotEqual" expectedValue:[NSString stringWithFormat:@"!/%@/i", (E)] actualValue:(A) filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_OBJECTS_NOT_EQUAL(E, A) if ([(E) isEqual:(A)]) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertObjectsNotEqual" expectedValue:@"unequal objects" actualValue:@"equal objects" filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_OBJECTS_NOT_IDENTICAL(E, A) if ((E) == (A)) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertObjectsNotIdentical" expectedValue:@"unidentical objects" actualValue:@"identical objects" filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_NOT_NIL(A) if (!(A)) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertNotNil" expectedValue:@"!null" actualValue:@"null" filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }

// logical assertions
#define ASSERT_TRUE(A) if (!(A)) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertTrue" expectedValue:@"true" actualValue:@"false" filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_FALSE(A) if (A) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertFalse" expectedValue:@"false" actualValue:@"true" filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }

// other handy assertions
#define ASSERT_EMPTY_STRING(A) if ((A) && ![(A) isEqualToString:@""]) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertEmptyString" expectedValue:@"nil or empty string" actualValue:@"non-empty string" filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }
#define ASSERT_NON_EMPTY_STRING(A) if (!(A) || [(A) isEqualToString:@""]) { @throw [[AssertionException alloc] initExceptionWithReason:@"assertNonEmptyString" expectedValue:@"non-empty string" actualValue:@"nil or empty string" filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__]; }

// fails
#define FAIL(M) @throw [[AssertionException alloc] initExceptionWithReason:@"fail" expectedValue:(M) actualValue:@"-" filename:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__];

